/* my super cycle core file V0.1
 * mSC.c
 *
 *  Created on: 2016-9-30
 *      Author: nkj
 */

#include "mSC.h"


typedef struct _msctaskcb
{
    emscTaskStatus tasksta;     //任务运行状态
    uint32_t timegap;           //任务运行间隔 ms
    uint32_t timecnt;           //任务运行计时 ms
    uint32_t timeout;           //任务执行周期 ms
    void *pPram;                //传入参数地址
    void (*handler)(void *p);   //任务函数，带一个参数
}mSCTaskCb,*pmSCTaskCb;

static volatile mSCTaskCb msctaskcb[MAXTASKNUM];

static volatile emscStatus mscsta = MSC_STOP;
static volatile uint32_t mscticks = 0;
static volatile uint32_t msctime = 0;
static volatile uint32_t mscfreq = MSCOREFREQ;//系统频率，修改系统频率时会重新初始化定时器

static void mscIdleTask(void *p);
static void mscSetupFreq(uint32_t freq);
static void mscTaskSchedulerStart(void);

/* msc 初始化
 * 函数名：void mscInit(void)
 * 输入：
 * 返回：
 */
void mscInit(void)
{
    uint32_t i = 0;
    mscStop();
    mscSetupFreq(MSCOREFREQ);
    for(i = 0;i < (sizeof(mSCTaskCb) * MAXTASKNUM);i ++)
    {
        ((uint8_t *)msctaskcb)[i] = 0;
    }
#if IDLETASKEN
    msctaskcb[MAXTASKNUM - 1].tasksta = MSC_TASK_MSDELAY;
#else
    msctaskcb[MAXTASKNUM - 1].tasksta = INVALID;
#endif
    msctaskcb[MAXTASKNUM - 1].timegap = 0;
    msctaskcb[MAXTASKNUM - 1].timecnt = 0;
    msctaskcb[MAXTASKNUM - 1].timeout = 0;
    msctaskcb[MAXTASKNUM - 1].pPram = NULL;
    msctaskcb[MAXTASKNUM - 1].handler = mscIdleTask;

#if QUEUECB
    qInit();
#endif

#if DISPLAYCB 
    displayInit();
#endif
}

/* msc设置系统频率
 * 函数名：static void mscSetupFreq(uint32_t freq)
 * 输入：
 * 返回：
 */
static void mscSetupFreq(uint32_t freq)
{
    mscfreq = freq;
    mscTickConfig(mscfreq);
}

/* msc启动
 * 函数名：void mscStart(void)
 * 输入：
 * 返回：
 */
void mscStart(void)
{
    mscsta = MSC_START;
    while(1)
    {
        mscTaskSchedulerStart();	//任务调度运行
    }
}

/* msc停止
 * 函数名：void mscStop(void)
 * 输入：
 * 返回：
 */
void mscStop(void)
{
    uint32_t i = 0;
    mscsta = MSC_STOP;
    mscticks = 0;
    msctime = 0;
    for(i = 0;i < (MAXTASKNUM - 1);i ++)
    {
        msctaskcb[i].timecnt = 0;
    }
}

/* 得到msc状态
 * 函数名：emscStatus getmSCSta(void)
 * 输入：
 * 返回：系统状态
 */
emscStatus getMSCSta(void)
{
    return (mscsta);
}

/* 得到msc频率
 * 函数名：uint32_t getmSCFreq(void)
 * 输入：
 * 返回：msc频率
 */
uint32_t getMSCFreq(void)
{
    return (mscfreq);
}

/* 得到msc运行时间
 * 函数名：uint32_t getmSCRunTime(void)
 * 输入：
 * 返回：运行时间
 */
uint32_t getMSCRunTime(void)
{
    return (msctime);
}

/* 得到msc运行ticks
 * 函数名：static uint32_t getMSCTicks(void)
 * 输入：
 * 返回：ticks
 */
static uint32_t getMSCTicks(void)
{
    return (mscticks);
}

/* SysTick 中断函数
 * 函数名：void SysTick_Handler(void)
 * 输入：
 * 返回：
 */
void mscTickIRQHandler(void)
{
    uint32_t i = 0;
    mscticks ++;
    if(MSC_START == getMSCSta())
    {
        msctime += (uint32_t)((1000)/mscfreq + 0.5);
        while((mscIdleTask) != (msctaskcb[i].handler))
        {
            if((MSC_TASK_MSDELAY == msctaskcb[i].tasksta) || (MSC_TASK_ZERODELAY == msctaskcb[i].tasksta))
                msctaskcb[i].timecnt += (uint32_t)((1000)/mscfreq + 0.5);

            i ++;
        }
    }
#if DISPLAYCB 
#if GRAPHICDISPLAYEN
    displayRefresh();
#endif
#endif
}

/* 任务调度
 * 函数名：void mscTaskSchedulerStart(void)
 * 输入：
 * 返回：
 */
static void mscTaskSchedulerStart(void)
{
    uint32_t i = 0,j = 0;
    while((msctaskcb[i].handler != (mscIdleTask)) && ((MSC_START == getMSCSta())))
    {
        j = 0;
        while((msctaskcb[j].handler != (mscIdleTask)))
        {
            if((MSC_TASK_ZERODELAY == msctaskcb[j].tasksta) && (NULL != msctaskcb[j].handler))
            {
                msctaskcb[i].timegap = msctaskcb[i].timecnt;
                msctaskcb[j].timecnt = 0;
                (msctaskcb[j].handler)(msctaskcb[j].pPram);
                msctaskcb[i].timegap = 0;
            }

            j ++;
        }

        if(MSC_TASK_INVALID == msctaskcb[i].tasksta)
        {
            msctaskcb[i].timecnt = 0;
        }
        else if((MSC_TASK_MSDELAY == msctaskcb[i].tasksta)
                && (NULL != msctaskcb[j].handler)
                && (msctaskcb[i].timecnt >= msctaskcb[i].timeout))
        {
            msctaskcb[i].timegap = msctaskcb[i].timecnt;
            msctaskcb[i].timecnt = 0;
            (msctaskcb[i].handler)(msctaskcb[i].pPram);
            msctaskcb[i].timegap = 0;
        }

        i ++;
    }
#if IDLETASKEN
    mscIdleTask(NULL);
#endif
}

/* 空闲任务
 * 函数名：void mscIdleTask(void *p)
 * 输入：传入参数指针
 * 返回：
 */
static void mscIdleTask(void *p)
{

#if TICKLESSEN
    mscTickLess();
#endif
}

/* 创建任务
 * 函数名：emscerrorcode mscCreateTask(emscTaskStatus tasksta,uint32_t periodic,uint32_t period,void *pPram,void (*handler))
 * 输入：
 * 		tasksta		任务运行状态
 *		periodic	任务运行计时 初始值ms
 *		period		任务执行周期 ms
 *		pPram		传入参数地址
 *		handler		任务函数，带一个参数
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscCreateTask( 	emscTaskStatus tasksta,
                                uint32_t periodic,
                                uint32_t period,
                                void *pPram,
                                void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(NULL == msctaskcb[i].handler)
        {
            msctaskcb[i].tasksta = tasksta;
            msctaskcb[i].timecnt = periodic;
            msctaskcb[i].timeout = period;
            msctaskcb[i].pPram   = pPram;
            msctaskcb[i].handler = handler;

            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_TASKNUMISMAX);
    return (MSC_SUCCESS);
}

/* 删除任务
 * 函数名：emscerrorcode mscDeleteTask(void (*handler))
 * 输入： handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscDeleteTask(void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            msctaskcb[i].tasksta = MSC_TASK_INVALID;
            msctaskcb[i].timecnt = 0;
            msctaskcb[i].timeout = 0;
            msctaskcb[i].pPram   = NULL;
            msctaskcb[i].handler = NULL;

            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 挂起任务,任务暂停，等待其他地方恢复其运行
 * 函数名：emscerrorcode mscPendTask(void (*handler))
 * 输入： handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscPendTask(void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            if(MSC_TASK_INVALID == msctaskcb[i].tasksta)
                return MSC_TASKINVALID;
            msctaskcb[i].tasksta = MSC_TASK_PEND;
            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 恢复任务至0延迟模式
 * 函数名：emscerrorcode mscRecoverTaskToZeroDelay(void (*handler))
 * 输入： handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscRecoverTaskToZeroDelay(void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            if(MSC_TASK_INVALID == msctaskcb[i].tasksta)
                return MSC_TASKINVALID;
            msctaskcb[i].tasksta = MSC_TASK_ZERODELAY;
            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 恢复任务至ms延迟模式
 * 函数名：emscerrorcode mscRecoverTaskToMsDelay(void (*handler))
 * 输入： handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscRecoverTaskToMsDelay(void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            if(MSC_TASK_INVALID == msctaskcb[i].tasksta)
                return MSC_TASKINVALID;
            msctaskcb[i].tasksta = MSC_TASK_MSDELAY;
            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 获得任务运行状态
 * 函数名：emscerrorcode mscGetTaskSta(emscTaskStatus *sta,void (*handler))
 * 输入： sta 接收状态的指针，handler 任务名
 * 返回：返回错误码
 */
emscerrorcode mscGetTaskSta(emscTaskStatus *sta,void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            *sta = 	(msctaskcb[i].tasksta);
            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 获得任务周期
 * 函数名：emscerrorcode mscGetTaskPeriod(uint32_t *period,void (*handler))
 * 输入： period 接收周期的指针，handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscGetTaskPeriod(uint32_t *period,void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            *period = (msctaskcb[i].timeout);
            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 获得任务计时
 * 函数名：emscerrorcode mscGetTaskTimeKeeping(uint32_t *periodic,void (*handler))
 * 输入： periodic 接收该任务已计时值，handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscGetTaskTimeKeeping(uint32_t *periodic,void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            *periodic = (msctaskcb[i].timecnt);
            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 获得任务还要多长时间才运行
 * 函数名：emscerrorcode mscGetTaskTimeSurplus(uint32_t *surplus,void (*handler))
 * 输入： surplus 接收该任务剩余计时，handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscGetTaskTimeSurplus(uint32_t *surplus,void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            *surplus = ((msctaskcb[i].timeout) - (msctaskcb[i].timecnt));
            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 获得任务传入参数
 * 函数名：emscerrorcode mscGetTaskPram(void *pram,void (*handler))
 * 输入： pram 接收该任务参数指针，handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscGetTaskPram(void *pram,void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            pram = (msctaskcb[i].pPram);
            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 获得任务实际运行间隔时间
 * 函数名：emscerrorcode mscGetTaskTimeGap(uint32_t *timegap,void (*handler))
 * 输入： timegap 接收该任务参数指针，handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscGetTaskTimeGap(uint32_t *timegap,void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            *timegap = msctaskcb[i].timegap;
            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 修改任务状态
 * 函数名：emscerrorcode mscSetTaskSta(emscTaskStatus sta,void (*handler))
 * 输入：sta 任务状态，handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscSetTaskSta(emscTaskStatus sta,void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            (msctaskcb[i].tasksta) = sta;
            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 修改任务周期
 * 函数名：emscerrorcode mscSetTaskTaskPeriod(uint32_t period,void (*handler))
 * 输入： period 要设置的计时值ms，handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscSetTaskPeriod(uint32_t period,void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            (msctaskcb[i].timeout) = period;
            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 修改任务计时值
 * 函数名：emscerrorcode mscSetTaskTimeKeeping(uint32 cnt,void (*handler))
 * 输入：time 要设置的计时值ms，handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscSetTaskTimeKeeping(uint32_t time,void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            (msctaskcb[i].timecnt) = time;
            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 向任务传入参数
 * 函数名：emscerrorcode mscSetTaskPram(void *pram,void (*handler))
 * 输入： 要设置的计时值ms，handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscSetTaskPram(void *pram,void (*handler))
{
    uint32_t i = 0;
    while((msctaskcb[i].handler != (mscIdleTask)))
    {
        if(handler == msctaskcb[i].handler)
        {
            (msctaskcb[i].pPram) = pram;
            break;
        }
        i ++;
    }
    if(i == (MAXTASKNUM - 1))
        return (MSC_NOTHISTASK);
    return (MSC_SUCCESS);
}

/* 恢复任务至0延迟模式从中断中
 * 函数名：emscerrorcode mscRecoverTaskToZeroDelayFromIRQ(void (*handler))
 * 输入： handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscRecoverTaskToZeroDelayFromIRQ(void (*handler))
{
#if TICKLESSEN
    mscWakeUp();//MCU从睡眠中醒来
#endif
    return (mscRecoverTaskToZeroDelay(handler));
}

/* 恢复任务至ms延迟模式从中断中
 * 函数名：emscerrorcode mscRecoverTaskToMsDelayFromIRQ(void (*handler))
 * 输入： handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscRecoverTaskToMsDelayFromIRQ(void (*handler))
{
#if TICKLESSEN
    mscWakeUp();//MCU从睡眠中醒来从中断中
#endif
    return (mscRecoverTaskToMsDelay(handler));
}

/* 修改任务状态
 * 函数名：emscerrorcode mscSetTaskStaFromIRQ(emscTaskStatus sta,void (*handler))
 * 输入：sta 任务状态，handler 任务名
 * 返回：成功返回0 失败返回错误码
 */
emscerrorcode mscSetTaskStaFromIRQ(emscTaskStatus sta,void (*handler))
{
#if TICKLESSEN
    mscWakeUp();//MCU从睡眠中醒来
#endif
    return (mscSetTaskSta(sta,handler));
}

/* 系统延时函数
 * 函数名：void mscMsDelay(uint32_t ms)
 * 输入： 要延时的时间ms
 * 返回：
 */
void mscMsDelay(uint32_t ms)
{
    uint32_t cnt = 0;
    cnt = getMSCTicks();
    if((0xffffffff - cnt) < pdMSC_MS_TO_TICKS(ms))
    {
        while(getMSCTicks() != 0);
        while((0xffffffff - pdMSC_MS_TO_TICKS(ms)) < (cnt - getMSCTicks()));
    }
    else
        while(getMSCTicks() < (cnt + pdMSC_MS_TO_TICKS(ms)));
}

